package com.xinqi.modules.chat.chat.group.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xinqi.common.base.enums.QrCodeEnum;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.base.user.Account;
import com.xinqi.common.core.constant.ConfigKeyConstants;
import com.xinqi.common.core.enums.ClassRoleEnum;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.modules.chat.chat.friend.service.ChatFriendService;
import com.xinqi.modules.chat.chat.group.convert.ChatGroupConvert;
import com.xinqi.modules.chat.chat.group.convert.ChatGroupUserConvert;
import com.xinqi.modules.chat.chat.group.domain.ChatGroupEntity;
import com.xinqi.modules.chat.chat.group.domain.ChatGroupUserEntity;
import com.xinqi.modules.chat.chat.group.dto.req.ChatClassUserGroupCreateDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatGroupAdminCreateDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatGroupAdminEditDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatGroupAdminQueryDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatGroupQueryDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatGroupUpdateDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ChatUserGroupCreateDTO;
import com.xinqi.modules.chat.chat.group.dto.req.ConversationSelectDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ChatGroupAdminResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ChatGroupInfoResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ChatGroupResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ChatGroupUserInfoResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ChatGroupUserResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ConversationResultDTO;
import com.xinqi.modules.chat.chat.group.dto.rsp.ShareSelectResultDTO;
import com.xinqi.modules.chat.chat.group.mapper.ChatGroupMapper;
import com.xinqi.modules.chat.chat.group.service.ChatGroupService;
import com.xinqi.modules.chat.chat.group.service.ChatGroupUserService;
import com.xinqi.modules.chat.enums.group.GroupAllForbiddenWordsEnum;
import com.xinqi.modules.chat.enums.group.GroupExamineEnum;
import com.xinqi.modules.chat.enums.group.GroupStatusEnum;
import com.xinqi.modules.chat.enums.group.GroupTypeEnum;
import com.xinqi.modules.chat.enums.group.GroupUserCommonEnum;
import com.xinqi.modules.chat.enums.group.GroupUserLeaderFlagEnum;
import com.xinqi.modules.chat.enums.group.GroupUserStatusEnum;
import com.xinqi.modules.chat.third.rongyun.service.RongyunService;
import com.xinqi.modules.chat.third.utils.ImageUtil;
import com.xinqi.modules.course.clazz.client.ClassStudentClient;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.sys.config.client.SysConfigClient;
import com.xinqi.modules.user.user.client.UserClient;
import com.xinqi.modules.user.user.dto.rsp.UserResultDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 群组表服务层实现
 *
 * @author: system
 * @date: 2023/01/12
 */
@Service("chatGroupService")
@RequiredArgsConstructor
public class ChatGroupServiceImpl extends BaseServiceImpl<ChatGroupMapper, ChatGroupEntity> implements ChatGroupService {

    private final ChatGroupConvert chatGroupConvert;

    private final ChatGroupUserConvert chatGroupUserConvert;

    private final UserClient userClient;

    private final ChatFriendService chatFriendService;

    private final ChatGroupUserService chatGroupUserService;

    private final ChatGroupMessageService chatGroupMessageService;

    private final ChatGroupMQService chatGroupMQService;

    private final SysConfigClient sysConfigClient;

    private final RongyunService rongyunService;

    private final ClassStudentClient classStudentClient;

    /**
     * 获取我的群聊(旧)
     *
     * @param operationUserId
     * @param keywords
     * @return
     */
    @DS("slaver")
    @Override
    public List<ChatGroupResultDTO> listByUserId(Long operationUserId, String keywords) {
        ChatGroupQueryDTO query = new ChatGroupQueryDTO();
        query.setOperationUserId(operationUserId);
        query.setKeywords(keywords);
        return this.baseMapper.listByQuery(query);
    }

    /**
     * 获取我的群聊（新）
     *
     * @param query
     * @return
     */
    @DS("slaver")
    @Override
    public List<ChatGroupResultDTO> listByQuery(ChatGroupQueryDTO query) {
        return this.baseMapper.listByQuery(query);
    }

    /**
     * 我的群列表 -- 分页
     *
     * @param pageable
     * @param query
     * @return
     */
    @Override
    @DS("slaver")
    public PageInfo<ChatGroupResultDTO> pageByQuery(Param pageable, ChatGroupQueryDTO query) {
        IPage<ChatGroupResultDTO> pageData = this.baseMapper.pageByQuery(Pages.page(pageable), query);
        return Pages.convert(pageData);
    }

    /**
     * 后台管理 -- 群列表分页
     *
     * @param pageable
     * @param query
     * @return
     */
    @Override
    @DS("slaver")
    public PageInfo<ChatGroupAdminResultDTO> pageAdmin(Param pageable, ChatGroupAdminQueryDTO query) {
        //排序
        if (CollectionUtils.isEmpty(pageable.getSorts())) {
            pageable.setSorts(new ArrayList<>());
        }
        pageable.getSorts().add("g.create_time,DESC");
        query.setGroupStatus(GroupStatusEnum.ONE.getCode());
        query.setGroupUserStatus(GroupUserStatusEnum.ONE.getCode());
        query.setGroupType(GroupTypeEnum.CUSTOMER_SERVICE.getCode());
        return Pages.convert(this.baseMapper.pageAdmin(Pages.page(pageable), query));
    }

    /**
     * 根据群聊ID获取群详情
     * 含群成员
     *
     * @param groupId
     * @param operationUserId
     * @return
     */
    @DS("slaver")
    @Override
    public ChatGroupResultDTO findByGroupIdIncludingUser(String groupId, Long operationUserId) {
        CommonErrors.BAD_REQUEST.check(StringUtils.isNotEmpty(groupId), MessageUtils.message("chat.chat.groupId.not.blank"));
        //会话列表使用，解散也可查询
        ChatGroupResultDTO chatGroupResultDTO = this.baseMapper.findByGroupId(groupId, operationUserId);
        if (Objects.isNull(chatGroupResultDTO) || Objects.isNull(chatGroupResultDTO.getId())) {
            return null;
        }
        //二维码生成转化
        chatGroupResultDTO.setQrCodeStr(chatGroupResultDTO.getQrCode());
        //群成员信息
        List<ChatGroupUserResultDTO> list = chatGroupUserService.findGroupId(groupId, operationUserId);
        chatGroupResultDTO.setGroupUserList(list);
        return chatGroupResultDTO;
    }

    /**
     * 根据群聊ID获取群详情
     *
     * @param groupId
     * @param operationUserId
     * @return
     */
    @DS("slaver")
    @Override
    public ChatGroupResultDTO findByGroupId(String groupId, Long operationUserId) {
        CommonErrors.BAD_REQUEST.check(StringUtils.isNotEmpty(groupId), MessageUtils.message("chat.chat.groupId.not.blank"));
        //会话列表使用，解散也可查询
        ChatGroupResultDTO chatGroupResultDTO = this.baseMapper.findByGroupId(groupId, operationUserId);
        if (Objects.isNull(chatGroupResultDTO) || Objects.isNull(chatGroupResultDTO.getId())) {
            return null;
        }
        //二维码生成转化
        chatGroupResultDTO.setQrCodeStr(chatGroupResultDTO.getQrCode());
        return chatGroupResultDTO;
    }

    /**
     * 根据群聊获取群聊信息
     *
     * @param query
     * @return
     */
    @DS("slaver")
    @Override
    public List<ChatGroupInfoResultDTO> groupInfoByGroupId(ChatGroupQueryDTO query) {
        CommonErrors.BAD_REQUEST.check(CollectionUtil.isNotEmpty(query.getGroupIds()), MessageUtils.message("chat.chat.groupId.not.blank"));
        return this.baseMapper.groupInfoByGroupId(query);
    }

    /**
     * 用户创建群组
     *
     * @param user 当前用户
     * @param dto  初始成员id集合
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatGroupResultDTO userCreate(Account user, ChatUserGroupCreateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(user.getId()), MessageUtils.message("chat.group.userId.not.blank"));
        //初始化群基本信息
        ChatGroupEntity group = initChatGroupEntity(user.getId());
        group.setGroupType(GroupTypeEnum.ORDINARY.getCode());
        //设置群组头像，名称信息
        List<Long> list = dto.getGroupUserIds();
        if (CollectionUtils.isNotEmpty(list)) {
            //防止传入的所选用户存在当前操作人员
            boolean exist = list.stream().anyMatch(userId -> user.getId().equals(userId));
            if (exist) {
                list.remove(user.getId());
            }
        } else {
            list = new ArrayList<>();
        }
        List<UserResultDTO> userList = CollectionUtil.isNotEmpty(list) ? R.as(userClient.findList(list)) : new ArrayList<>();
        CommonErrors.BAD_REQUEST.check(userList != null && userList.size() > 1, MessageUtils.message("chat.group.create.user.length.valid"));
        setChatGroupEntity(group, userList);

        //在融云创建群组 -- 用户主动发起，成功则成功，失败则失败
        boolean groupCreateFlag = rongyunService.creatGroup(group.getGroupId(), group.getGroupName(), group.getUserId().toString());
        CommonErrors.BAD_REQUEST.check(groupCreateFlag, MessageUtils.message("chat.group.rongyun.creat.fail"));
        //开始创建群
        createGroup(group, user, userList);
        return Optional.of(group).map(chatGroupConvert::convert).orElse(null);
    }

    /**
     * 班级创建群
     *
     * @param user 当前用户
     * @param dto  ChatClassUserGroupCreateDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatGroupResultDTO classCreate(Account user, ChatClassUserGroupCreateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(user.getId()), MessageUtils.message("chat.group.userId.not.blank"));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getClassId()), MessageUtils.message("chat.group.classId.not.blank"));

        // 校验班级群聊是否已创建
        ChatGroupEntity groupEntity = this.getOne(wrapperClass(dto.getClassId()));
        if (Objects.nonNull(groupEntity)) {
            return chatGroupConvert.convert(groupEntity);
        }

        //初始化群基本信息
        ChatGroupEntity group = initChatGroupEntity(user.getId());
        group.setGroupType(GroupTypeEnum.ORDINARY.getCode());
        //设置群组头像，名称信息
        List<Long> list = dto.getGroupUserIds();
        if (CollectionUtils.isNotEmpty(list)) {
            //防止传入的所选用户存在当前操作人员
            boolean exist = list.stream().anyMatch(userId -> user.getId().equals(userId));
            if (exist) {
                list.remove(user.getId());
            }
        } else {
            list = new ArrayList<>();
        }

        // 获取群成员列表
        List<UserResultDTO> userList = CollectionUtil.isNotEmpty(list) ? R.as(userClient.findList(list)) : new ArrayList<>();

        setChatGroupEntity(group, userList);
        String classGroupName = dto.getCourseName() + "•" + dto.getClassName();
        group.setGroupName(classGroupName);
        group.setClassId(dto.getClassId());
        //在融云创建群组
        chatGroupMQService.sendCreateMessage(group, user.getId());
        //开始时创建群
        createGroup(group, user, userList);
        return Optional.of(group).map(chatGroupConvert::convert).orElse(null);
    }

    /**
     * 管理端创建群
     *
     * @param user
     * @param dto
     * @return
     */
    @Override
    public Boolean createAdmin(Account user, ChatGroupAdminCreateDTO dto) {
        //初始化群基本信息
        ChatGroupEntity group = initChatGroupEntity(user.getId());
        String herdDefault = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_DEFAULT_AVATAR));
        group.setGroupType(GroupTypeEnum.CUSTOMER_SERVICE.getCode());
        group.setAvatar(herdDefault);
        group.setGroupName(dto.getGroupName());
        group.setRemark(dto.getRemark());

        //在融云创建群组 -- 用户主动发起，成功则成功，失败则失败
        boolean groupCreateFlag = rongyunService.creatGroup(group.getGroupId(), group.getGroupName(), group.getUserId().toString());
        CommonErrors.BAD_REQUEST.check(groupCreateFlag, MessageUtils.message("chat.group.rongyun.creat.fail"));
        //开始创建群
        createGroup(group, user, new ArrayList<>());
        return groupCreateFlag;
    }

    /**
     * 管理端修改群
     *
     * @param user
     * @param dto
     * @return
     */
    @Override
    public Boolean editAdmin(Account user, ChatGroupAdminEditDTO dto) {
        ChatGroupEntity entity = Optional.ofNullable(this.baseMapper.selectOne(wrapper(dto.getGroupId())))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.group.not.blank")));
        entity.setGroupName(dto.getGroupName());
        entity.setRemark(dto.getRemark());
        //修改群名
        if (StringUtils.isNotEmpty(dto.getGroupName()) && !Objects.equals(dto.getGroupName(), entity.getGroupName())) {
            //融云更新群组名称
            chatGroupMQService.sendRenameMessage(user, entity);
            //修改群名称小灰条通知消息
            chatGroupMessageService.sendRenameMessage(user, entity);
        }
        return this.updateById(entity);
    }

    /**
     * 设置群（仅管理和群主能操作）
     *
     * @param user
     * @param dto  ChatGroupUpdateDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setChatGroup(Account user, ChatGroupUpdateDTO dto) {
        ChatGroupEntity old = Optional.ofNullable(this.baseMapper.selectById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.group.not.blank")));
        CommonErrors.BAD_REQUEST.check(!Objects.equals(GroupStatusEnum.TWO.getCode(), old.getStatus()), MessageUtils.message("chat.group.group.is.dissolution"));
        ChatGroupEntity entity = chatGroupConvert.update(dto);
        entity.setGroupId(old.getGroupId());

        ChatGroupUserEntity groupUser = chatGroupUserService.checkAdministration(user.getId(), old.getGroupId());
        //修改群名
        if (StringUtils.isNotEmpty(dto.getGroupName()) && !Objects.equals(dto.getGroupName(), old.getGroupName())) {
            //融云更新群组名称
            chatGroupMQService.sendRenameMessage(user, entity);
            //修改群名称小灰条通知消息
            chatGroupMessageService.sendRenameMessage(user, entity);
        }
        //修改禁言状态
        if (Objects.nonNull(dto.getAllForbiddenWords()) && !Objects.equals(dto.getAllForbiddenWords(), old.getAllForbiddenWords())) {
            // 获取普通成员列表信息
            LambdaQueryWrapper<ChatGroupUserEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ChatGroupUserEntity::getGroupId, old.getGroupId());
            wrapper.eq(ChatGroupUserEntity::getLeaderFlag, GroupUserLeaderFlagEnum.THREE.getCode());
            List<ChatGroupUserEntity> groupUsers = chatGroupUserService.list(wrapper);
            List<String> userIds = groupUsers.stream().map(item -> Convert.toStr(item.getUserId())).collect(Collectors.toList());
            if (Objects.equals(GroupAllForbiddenWordsEnum.ZERO.getCode(), dto.getAllForbiddenWords())) {
                entity.setAllForbiddenWords(GroupAllForbiddenWordsEnum.ZERO.getCode());
                //融云解除禁言
                chatGroupMQService.sendCancelProhibitionMessage(entity, userIds);
                //解除群组禁言小灰条通知消息
                chatGroupMessageService.sendCancelProhibitionMessage(user, groupUser);
            } else if (Objects.equals(GroupAllForbiddenWordsEnum.ONE.getCode(), dto.getAllForbiddenWords())) {
                //融云添加禁言
                entity.setAllForbiddenWords(GroupAllForbiddenWordsEnum.ONE.getCode());
                //融云添加禁言
                chatGroupMQService.sendProhibitionMessage(entity, userIds);
                //群组禁言小灰条通知消息
                chatGroupMessageService.sendProhibitionMessage(user, groupUser);
            }
        }

        return this.updateById(entity);
    }

    /**
     * 解散群(仅群主可操作)
     *
     * @param user user
     * @param id   id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean disbandChatGroup(Account user, Long id) {
        ChatGroupEntity old = Optional.ofNullable(this.baseMapper.selectById(id))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.group.not.blank")));
        CommonErrors.BAD_REQUEST.check(!Objects.equals(GroupStatusEnum.TWO.getCode(), old.getStatus()), MessageUtils.message("chat.group.group.is.dissolution"));
        ChatGroupUserEntity groupUser = chatGroupUserService.getOne(wrapper(user.getId(), old.getGroupId()).last("LIMIT 1"));
        if (!Objects.equals(GroupUserLeaderFlagEnum.ONE.getCode(), groupUser.getLeaderFlag())) {
            CommonErrors.BAD_REQUEST.check(false, MessageUtils.message("chat.group.is.not.leader"));
        }
        //移除所有群成员
        chatGroupUserService.deleteByGroupId(old.getGroupId());
        //解散群
        old.setStatus(GroupStatusEnum.TWO.getCode());
        //解散群组小灰条通知消息
        chatGroupMessageService.sendDismissMessage(user, old.getGroupId());
        //融云解散群组
        chatGroupMQService.sendDismissMessage(old);
        return this.updateById(old);
    }

    /**
     * 解散班级群(仅群主可操作)
     *
     * @param classId 班级ID
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean classDisbandGroup(Long classId) {
        ChatGroupEntity groupEntity = this.getOne(wrapperClass(classId));
        if (Objects.isNull(groupEntity)) {
            return Boolean.TRUE;
        }
        //移除所有群成员
        chatGroupUserService.deleteByGroupId(groupEntity.getGroupId());
        //解散群
        groupEntity.setStatus(GroupStatusEnum.TWO.getCode());
        UserResultDTO user = R.as(userClient.findById(groupEntity.getUserId()));
        //解散群组小灰条通知消息
        chatGroupMessageService.sendDismissMessage(user, groupEntity);
        //融云解散群组
        chatGroupMQService.sendDismissMessage(groupEntity);
        return this.updateById(groupEntity);
    }

    /**
     * 管理端解散群
     *
     * @param user
     * @param groupId
     * @return
     */
    @Override
    public Boolean disbandAdmin(Account user, String groupId) {
        ChatGroupEntity entity = Optional.ofNullable(this.baseMapper.selectOne(wrapper(groupId)))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.group.not.blank")));
        //移除所有群成员
        chatGroupUserService.deleteByGroupId(entity.getGroupId());
        //解散群
        entity.setStatus(GroupStatusEnum.TWO.getCode());
        //解散群组小灰条通知消息
        chatGroupMessageService.sendDismissMessage(user, groupId);
        //融云解散群组
        chatGroupMQService.sendDismissMessage(entity);
        return this.updateById(entity);
    }

    /**
     * 转让群(仅群主可操作)
     *
     * @param user user
     * @param dto  ChatGroupUpdateDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean shiftChatGroup(Account user, ChatGroupUpdateDTO dto) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(dto.getUserId()), MessageUtils.message("chat.group.shift.userId.not.blank"));
        ChatGroupEntity group = Optional.ofNullable(this.baseMapper.selectById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.group.not.blank")));
        CommonErrors.BAD_REQUEST.check(!Objects.equals(GroupStatusEnum.TWO.getCode(), group.getStatus()), MessageUtils.message("chat.group.group.is.dissolution"));
        ChatGroupUserResultDTO mainUser = Optional.ofNullable(chatGroupUserService.selectByUserIdAndGroupId(user.getId(), group.getGroupId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.user.not.group")));
        CommonErrors.BAD_REQUEST.check(Objects.equals(GroupUserLeaderFlagEnum.ONE.getCode(), mainUser.getLeaderFlag()), MessageUtils.message("chat.group.is.not.leader"));
        List<ChatGroupUserEntity> newGroupUser = new ArrayList<>();
        // 获取转让成员
        ChatGroupUserResultDTO shiftUser = Optional.ofNullable(chatGroupUserService.selectByUserIdAndGroupId(dto.getUserId(), group.getGroupId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("chat.group.shift.user.not.blank")));
        if (Objects.equals(shiftUser.getUserId(), mainUser.getUserId())) {
            return Boolean.TRUE;
        }

        ChatGroupUserEntity userEntity1 = new ChatGroupUserEntity();
        userEntity1.setId(shiftUser.getId());
        userEntity1.setLeaderFlag(GroupUserLeaderFlagEnum.ONE.getCode());
        newGroupUser.add(userEntity1);
        ChatGroupUserEntity userEntity2 = new ChatGroupUserEntity();
        userEntity2.setId(mainUser.getId());
        userEntity2.setLeaderFlag(GroupUserLeaderFlagEnum.THREE.getCode());
        newGroupUser.add(userEntity2);

        //转让时，群若是禁言
        if (Objects.equals(GroupAllForbiddenWordsEnum.ONE.getCode(), group.getAllForbiddenWords())) {
            //解除新群主禁言
            chatGroupMQService.sendCancelProhibitionMessage(group, shiftUser.getUserId().toString());
            //添加原群主禁言
            chatGroupMQService.sendProhibitionMessage(group, mainUser.getUserId().toString());
        }

        // 保存成员身份修改
        chatGroupUserService.updateBatchById(newGroupUser);
        group.setUserId(shiftUser.getUserId());

        //转让群主小灰条通知消息
        chatGroupMessageService.sendShiftLeaderMessage(mainUser, shiftUser, group.getGroupId());

        return this.updateById(group);
    }


    /**
     * 转让班级群(仅群主可操作)
     *
     * @Title:
     * @MethodName: classShiftGroup
     * [classId, userId]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/30 10:05
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean classShiftGroup(Long classId, Long userId) {
        /*
         * 转让班级 -- 接收人可以是系统任意用户
         * 1.查询班级群
         * 2.查看接收人是否在群
         * 3.在群则改为群主，原群主退群
         * 4.不在群则加入群，修改为群主，原群主退群
         */
        //查询班级群
        ChatGroupEntity group = this.getOne(wrapperClass(classId));
        if (Objects.isNull(group)) {
            return Boolean.TRUE;
        }
        //获取需要添加的用户列表
        UserResultDTO user = R.as(userClient.findById(userId));
        if (Objects.isNull(user)) {
            return Boolean.TRUE;
        }

        //查看接收人是否在群
        LambdaQueryWrapper<ChatGroupUserEntity> shiftWrapper = Queries.lambda();
        shiftWrapper.eq(ChatGroupUserEntity::getUserId, userId)
            .eq(ChatGroupUserEntity::getGroupId, group.getGroupId())
            .in(ChatGroupUserEntity::getStatus, Arrays.asList(GroupUserStatusEnum.ONE.getCode(), GroupUserStatusEnum.ZERO.getCode()))
            .last("LIMIT 1");
        ChatGroupUserEntity shiftUser = chatGroupUserService.getOne(shiftWrapper);

        //查询原群主
        LambdaQueryWrapper<ChatGroupUserEntity> mainWrapper = Queries.lambda();
        mainWrapper.eq(ChatGroupUserEntity::getGroupId, group.getGroupId())
            .eq(ChatGroupUserEntity::getStatus, GroupUserStatusEnum.ONE.getCode())
            .eq(ChatGroupUserEntity::getLeaderFlag, GroupUserLeaderFlagEnum.ONE.getCode())
            .last("LIMIT 1");
        ChatGroupUserEntity mainUser = chatGroupUserService.getOne(mainWrapper);
        Account account = new Account();

        //原群主退群
        if (Objects.nonNull(mainUser)) {
            if (Objects.equals(userId, mainUser.getUserId())) {
                return Boolean.TRUE;
            }
            UserResultDTO userResultDTO = R.as(userClient.findById(mainUser.getUserId()));
            if (Objects.nonNull(userResultDTO)) {
                account.setId(userResultDTO.getId());
                account.setUsername(userResultDTO.getUsername());
                account.setNickname(userResultDTO.getNickname());
                account.setStatus(userResultDTO.getStatus());
                account.setIsAdmin(userResultDTO.getIsAdmin());
                account.setIsSuperAdmin(userResultDTO.getIsSuperAdmin());
            }
            //退出群组小灰条通知消息
            chatGroupMessageService.sendQuitMessage(userResultDTO, mainUser.getGroupId(), userId.toString());
            //融云退群
            chatGroupMQService.sendQuitMessage(group, mainUser.getUserId().toString());

            chatGroupUserService.deleteById(mainUser.getId());
        }

        if (Objects.nonNull(shiftUser)) {
            //审核中，则改为正常入群
            if (Objects.equals(GroupUserStatusEnum.ZERO.getCode(), shiftUser.getStatus())) {
                shiftUser.setStatus(GroupUserStatusEnum.ONE.getCode());
            }
            //在群则改为群主
            shiftUser.setLeaderFlag(GroupUserLeaderFlagEnum.ONE.getCode());
            shiftUser.setRenames(user.getNickname() + ClassRoleEnum.TEACHER.getDescribe());
            chatGroupUserService.updateById(shiftUser);
        } else {
            ClassStudentResultDTO studentResult = R.as(classStudentClient.findByStudentId(classId, userId));

            //不在群则加入群，修改为群主
            shiftUser = new ChatGroupUserEntity(group.getGroupId(), user.getId(), "", "", "", "");
            shiftUser.setStatus(GroupUserStatusEnum.ONE.getCode());
            shiftUser.setLeaderFlag(GroupUserLeaderFlagEnum.ONE.getCode());
            shiftUser.setCommon(GroupUserCommonEnum.UNKNOWN.getCode());
            if (Objects.nonNull(studentResult)) {
                if (Objects.equals("本人", studentResult.getRelationship())) {
                    shiftUser.setRenames(studentResult.getStudentName());
                } else {
                    String renames = MessageFormat.format("{0}{1}", Optional.ofNullable(studentResult.getStudentName()).orElse("")
                        , Optional.ofNullable(studentResult.getRelationship()).orElse(""));
                    shiftUser.setRenames(renames);
                }
            }
            //融云加群
            chatGroupMQService.sendAddMessage(group, shiftUser.getUserId().toString());

            chatGroupUserService.save(shiftUser);
            //添加群成员小灰条通知消息
            List<UserResultDTO> userResultList = new ArrayList<>();
            userResultList.add(user);
            chatGroupMessageService.sendAddMessage(account, userResultList, group.getGroupId());
        }

        //转让时，群若是禁言，则解除禁言(由于禁言针对的是群成员，群主和管理员不禁言，所以解除禁言在群成员身份更改之前)
        if (Objects.equals(GroupAllForbiddenWordsEnum.ONE.getCode(), group.getAllForbiddenWords())) {
            // 获取普通成员列表信息
            LambdaQueryWrapper<ChatGroupUserEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ChatGroupUserEntity::getGroupId, group.getGroupId());
            wrapper.eq(ChatGroupUserEntity::getLeaderFlag, GroupUserLeaderFlagEnum.THREE.getCode());
            List<ChatGroupUserEntity> groupUsers = chatGroupUserService.list(wrapper);
            List<String> userIds = groupUsers.stream().map(item -> Convert.toStr(item.getUserId())).collect(Collectors.toList());
            //解除群组禁言MQ处理
            chatGroupMQService.sendCancelProhibitionMessage(group, userIds);

            group.setAllForbiddenWords(GroupAllForbiddenWordsEnum.ZERO.getCode());
        }
        List<ChatGroupUserResultDTO> list = chatGroupUserService.getGroupUserOrderByCreateTime(group.getGroupId(), GroupUserStatusEnum.ONE.getCode(), 2);
        if (CollectionUtil.isNotEmpty(list)) {
            //生成新头像
            String avatar = null;
            if (list.size() > 1) {
                try {
                    String defaultAvatar = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_DEFAULT_AVATAR));
                    String groupImg = group.getGroupId() + "groupimg" + System.currentTimeMillis();
                    avatar = ImageUtil.composite2(list.get(0).getAvatar(), list.get(1).getAvatar(), groupImg, defaultAvatar);
                } catch (Exception | Error e) {
                    avatar = list.get(0).getAvatar();
                }
            } else {
                avatar = list.get(0).getAvatar();
            }
            group.setAvatar(avatar);
        }
        //保存修改后的群主
        group.setUserId(userId);
        //转让群主小灰条通知消息
        ChatGroupUserResultDTO shiftUserDto = chatGroupUserConvert.convert(shiftUser);
        shiftUserDto.setNickname(user.getNickname());
        ChatGroupUserResultDTO mainUserDto = chatGroupUserConvert.convert(mainUser);
        if (Objects.nonNull(mainUserDto)) {
            mainUserDto.setNickname(account.getNickname());
        }
        chatGroupMessageService.sendShiftLeaderMessage(mainUserDto, shiftUserDto, group.getGroupId());
        return this.updateById(group);
    }

    /**
     * 账号注销 -- 聊天模块业务变动
     *
     * @Title:
     * @MethodName: accountCancel
     * [userId]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/10 14:31
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean accountCancel(Long userId) {
        //1.好友 -- 删除好友
        chatFriendService.deleteFriendByUserId(userId);

        //2.获取用户的所有群
        List<ChatGroupResultDTO> groupList = this.listByUserId(userId, null);
        if (CollectionUtils.isNotEmpty(groupList)) {
            groupList.stream().forEach(group -> {
                ChatGroupUserResultDTO groupUser = chatGroupUserService.selectByUserIdAndGroupId(userId, group.getGroupId());
                chatGroupUserService.leaderExitGroup(chatGroupConvert.convert(group), groupUser);
            });
        }

        //3.融云注销MQ处理
        chatGroupMQService.accountCancel(userId);

        return Boolean.TRUE;
    }

    /**
     * 群组汇总列表只包含头像名称和会话ID
     *
     * @param dto
     * @return
     */
    @DS("slaver")
    @Override
    public List<ConversationResultDTO> selectConversation(ConversationSelectDTO dto) {
        dto.setGroupStatus(GroupStatusEnum.ONE.getCode());
        dto.setUserStatus(GroupUserStatusEnum.ONE.getCode());
        return this.baseMapper.selectConversation(dto);
    }

    /**
     * 根据班级查询班级群
     *
     * @param userId
     * @param classId
     * @return
     */
    @DS("slaver")
    @Override
    public R<ChatGroupUserResultDTO> groupInfoByClass(Long userId, Long classId) {
        ChatGroupEntity groupEntity = this.getOne(wrapperClass(classId));
        if (Objects.isNull(groupEntity)) {
            return R.fail(MessageUtils.message("chat.group.class.not.blank"));
        }
        ChatGroupUserResultDTO resultDTO = chatGroupUserService.selectByUserIdAndGroupId(userId, groupEntity.getGroupId());
        if (Objects.isNull(resultDTO)) {
            return R.fail(MessageUtils.message("chat.group.user.not.group"));
        }
        return R.ok(resultDTO);
    }

    /**
     * 根据用户和群查询，返回群组信息，用户信息，在群则返回群组成员身份信息
     *
     * @param userId
     * @param groupId 群Id(融云)
     * @return
     */
    @DS("slaver")
    @Override
    public ChatGroupUserInfoResultDTO infoByUserIdAndGroupId(Long userId, String groupId) {
        CommonErrors.BAD_REQUEST.check(StringUtils.isNotEmpty(groupId), MessageUtils.message("chat.chat.groupId.not.blank"));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(userId), MessageUtils.message("user.id.not.black"));
        return this.baseMapper.infoByUserIdAndGroupId(groupId, userId);
    }

    /**
     * 管理端群详情
     *
     * @param groupId
     * @return
     */
    @Override
    public ChatGroupAdminResultDTO infoAdmin(String groupId) {
        ChatGroupAdminQueryDTO query = new ChatGroupAdminQueryDTO();
        query.setGroupId(groupId);
        query.setGroupStatus(GroupStatusEnum.ONE.getCode());
        query.setGroupUserStatus(GroupUserStatusEnum.ONE.getCode());
        return this.baseMapper.infoAdmin(query);
    }

    /**
     * 群组汇总列表只包含头像名称和会话ID
     *
     * @param userId
     * @return
     */
    @DS("slaver")
    @Override
    public ShareSelectResultDTO getSharePersonalInfo(Long userId) {
        UserResultDTO user = R.as(userClient.findById(userId));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(user), MessageUtils.message("user.is.not.existence"));
        ShareSelectResultDTO share = new ShareSelectResultDTO();
        share.setUserId(user.getId());
        share.setAvatar(user.getAvatar());
        share.setNickname(user.getNickname());
        share.setXinqiNumber(user.getXinqiNumber());
        share.setTitle("新奇好友分享");
        share.setContent("新奇课堂用户信息分享");
        //获取连接地址
        String shareUrl = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_SHARE_HTML));
        //获取logo
        String logo = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_DEFAULT_LOGO));
        share.setLogo(logo);
        shareUrl = shareUrl + "?userId=%s&nickName=%s&avatar=%s";
        share.setUrl(String.format(shareUrl, user.getId(), user.getNickname(), user.getAvatar()));
        return share;
    }

    private LambdaQueryWrapper<ChatGroupEntity> wrapperClass(Long classId) {
        LambdaQueryWrapper<ChatGroupEntity> wrapper = Queries.lambda();
        wrapper.eq(ChatGroupEntity::getClassId, classId)
            .eq(ChatGroupEntity::getStatus, GroupStatusEnum.ONE.getCode())
            .last("LIMIT 1");
        return wrapper;
    }

    /**
     * 根据班级ID获取群组信息
     *
     * @param userId
     * @param groupId
     * @return
     */
    private LambdaQueryWrapper<ChatGroupUserEntity> wrapper(Long userId, String groupId) {
        LambdaQueryWrapper<ChatGroupUserEntity> wrapper = Queries.lambda();
        Queries.accept(userId, v -> wrapper.eq(ChatGroupUserEntity::getUserId, v));
        Queries.accept(groupId, v -> wrapper.eq(ChatGroupUserEntity::getGroupId, v));
        wrapper.eq(ChatGroupUserEntity::getStatus, GroupUserStatusEnum.ONE.getCode());
        return wrapper;
    }

    private LambdaQueryWrapper<ChatGroupEntity> wrapper(String groupId) {
        LambdaQueryWrapper<ChatGroupEntity> wrapper = Queries.lambda();
        wrapper.eq(ChatGroupEntity::getGroupId, groupId)
            .eq(ChatGroupEntity::getStatus, GroupStatusEnum.ONE.getCode())
            .last("LIMIT 1");
        return wrapper;
    }

    private void createGroup(ChatGroupEntity group, Account user, List<UserResultDTO> userList) {
        //保存新建群
        this.save(group);
        if (CollectionUtils.isNotEmpty(userList)) {
            // 过滤熟悉新奇模拟学员信息
            List<UserResultDTO> newUserList = userList.stream().filter(item -> !item.getMobile().contains("192000000")).collect(Collectors.toList());
            // 融云加群
            if (CollectionUtils.isNotEmpty(newUserList)) {
                List<String> userIds = newUserList.stream().map(item -> Convert.toStr(item.getId())).collect(Collectors.toList());
                chatGroupMQService.sendAddMessage(group, userIds);
            }
        }
        //创建群聊小灰条通知消息
        chatGroupMessageService.sendCreateMessage(user, group);
        //保存群组成员信息
        this.saveGroupUser(user, group, userList);
        //添加群成员小灰条通知消息
        chatGroupMessageService.sendAddMessage(user, userList, group.getGroupId());
    }

    /**
     * 初始化群基本信息
     *
     * @param userId 创建人Id
     * @return ChatGroupEntity
     */
    private ChatGroupEntity initChatGroupEntity(Long userId) {
        ChatGroupEntity group = new ChatGroupEntity();
        String groupId = userId + "own" + System.currentTimeMillis();
        group.setUserId(userId);
        group.setGroupId(groupId);
        Map<String, Object> qrMap = new HashMap<>();
        qrMap.put("type", QrCodeEnum.QR_GROUP.getCode());
        qrMap.put("code", groupId);

        // 设置群二维码
        String genQrCodeUrl = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_GEN_QRCODE_URL));
        String content = genQrCodeUrl + JSON.toJSONString(qrMap);
        group.setQrCode(content);

        //创建群聊后默认关闭“加群是否审核，默认关闭“全员禁言”
        group.setExamine(GroupExamineEnum.ZERO.getCode());
        group.setAllForbiddenWords(GroupAllForbiddenWordsEnum.ZERO.getCode());
        group.setStatus(GroupStatusEnum.ONE.getCode());
        return group;
    }

    /**
     * 设置群头像
     *
     * @param group        ChatGroupEntity
     * @param groupUserIds List<UserResultDTO> 邀请加入群成员集合
     */
    private void setChatGroupEntity(ChatGroupEntity group, List<UserResultDTO> groupUserIds) {
        Map<String, String> map = this.initGroupNameAvatar(groupUserIds, group);
        String groupName = map.get("name") != null ? map.get("name") : "";
        String avatar = map.get("avatar") != null ? map.get("avatar") : "";
        group.setGroupName(groupName);
        group.setAvatar(avatar);
    }

    /**
     * 保存群成员
     *
     * @param group ChatGroupEntity
     * @param list  List<UserResultDTO> 邀请加入群成员集合
     * @return
     */
    private Boolean saveGroupUser(Account user, ChatGroupEntity group, List<UserResultDTO> list) {
        List<ChatGroupUserEntity> groupUserEntities = this.initGroupUserList(user, group, list);
        return chatGroupUserService.saveBatch(groupUserEntities);
    }

    /**
     * 初始化群头像，群名称
     *
     * @param list  List<UserResultDTO> 邀请加入群成员集合
     * @param group ChatGroupEntity   群信息
     * @return Map
     */
    private Map<String, String> initGroupNameAvatar(List<UserResultDTO> list, ChatGroupEntity group) {
        UserResultDTO user = R.as(userClient.findById(group.getUserId()));
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(user), MessageUtils.message("user.is.not.existence"));
        //获取系统默认头像
        String herdDefault = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_DEFAULT_AVATAR));
        StringBuilder name = new StringBuilder(user.getNickname());
        List<String> avatarList = new ArrayList<>();
        avatarList.add(user.getAvatar() == null ? herdDefault : user.getAvatar());
        if (Objects.nonNull(list)) {
            for (int i = 0; i < list.size(); i++) {
                if (i < 1) {
                    avatarList.add(list.get(i).getAvatar() == null ? herdDefault : list.get(i).getAvatar());
                }
                if (i < 2) {
                    name.append(",").append(list.get(i).getNickname());
                } else if (i == 2) {
                    name.append("...");
                }

            }
        }
        String avatar = null;
        if (avatarList.size() > 1) {
            try {
                String defaultAvatar = R.as(sysConfigClient.getConfigKey(ConfigKeyConstants.SYS_DEFAULT_AVATAR));
                String groupImg = group.getGroupId() + "groupimg" + System.currentTimeMillis();
                avatar = ImageUtil.composite2(avatarList.get(0), avatarList.get(1), groupImg, defaultAvatar);
            } catch (Exception | Error e) {
                avatar = avatarList.get(0);
            }
        } else {
            avatar = avatarList.get(0);
        }

        Map<String, String> map = new HashMap<>();
        map.put("name", name.toString());
        map.put("avatar", avatar);
        return map;
    }

    /**
     * 初始群成员列表
     *
     * @param user
     * @param group
     * @param list
     * @return
     */
    private List<ChatGroupUserEntity> initGroupUserList(Account user, ChatGroupEntity group, List<UserResultDTO> list) {
        List<ChatGroupUserEntity> groupUserEntities = new ArrayList<>();
        ChatGroupUserEntity groupOne = new ChatGroupUserEntity(group.getGroupId(), user.getId(), "", "", "", "");
        groupOne.setStatus(GroupUserStatusEnum.ONE.getCode());
        groupOne.setLeaderFlag(GroupUserLeaderFlagEnum.ONE.getCode());
        groupOne.setCommon(GroupUserCommonEnum.UNKNOWN.getCode());

        // 赋值 班级群 成员昵称
        if (Objects.nonNull(group.getClassId())) {
            ClassStudentResultDTO studentResult = R.as(classStudentClient.findByStudentId(group.getClassId(), user.getId()));
            if (Objects.nonNull(studentResult)) {
                String renames = MessageFormat.format("{0}{1}", Optional.ofNullable(studentResult.getStudentName()).orElse("")
                    , Optional.ofNullable(studentResult.getRelationship()).orElse(""));
                groupOne.setRenames(renames);
            }
        }
        groupUserEntities.add(groupOne);
        for (UserResultDTO dto : list) {
            //防止数据混乱，创建人存在群主和成员两条记录
            if (!Objects.equals(group.getUserId(), dto.getId())) {
                ChatGroupUserEntity groupUser = new ChatGroupUserEntity(group.getGroupId(), dto.getId(), "", "", "", "");
                groupUser.setStatus(GroupUserStatusEnum.ONE.getCode());
                groupUser.setLeaderFlag(GroupUserLeaderFlagEnum.THREE.getCode());
                groupUser.setCommon(GroupUserCommonEnum.UNKNOWN.getCode());
                groupUserEntities.add(groupUser);
            }

        }
        return groupUserEntities;
    }

}
